import { UploadProps } from 'antd';

export const customRequest: NonNullable<UploadProps['customRequest']> =
  function ({
    file,
    data,
    action,
    filename,
    headers = {},
    method = 'POST',
    withCredentials,
    onProgress,
    onSuccess,
    onError,
  }) {
    const publish = function () {
      const xhr = new XMLHttpRequest();
      const formData = new FormData();
      if (data) {
        Object.keys(data).forEach((key) => {
          const value = data[key];
          if (Array.isArray(value)) {
            value.forEach((item) => {
              formData.append(`${key}[]`, item);
            });
            return;
          }
          formData.append(key, value as string | Blob);
        });
      }
      if (file instanceof Blob) {
        formData.append(
          filename ?? (file as any).name,
          file,
          (file as any).name,
        );
      } else {
        formData.append(filename ?? file, file);
      }

      if ('withCredentials' in xhr && withCredentials) {
        xhr.withCredentials = true;
      }

      if (onProgress && xhr.upload) {
        xhr.upload.onprogress = function progress(e) {
          if (e.total > 0) {
            Object.assign(e, { percent: (e.loaded / e.total) * 100 });
          }
          onProgress(e);
        };
      }

      xhr.onerror = function error(e) {
        onError?.(e, publish);
      };

      xhr.onload = function onload() {
        const text = xhr.response || xhr.responseText;
        const body =
          xhr.responseType === 'json' && text ? JSON.parse(text) : text;

        if (xhr.status < 200 || xhr.status >= 300) {
          const msg = `cannot ${method} ${action} ${xhr.status}'`;
          const err = new Error(msg) as any;
          err.status = xhr.status;
          err.method = method;
          err.url = action;
          onError?.(err, publish);
          return;
        } else {
          const key = formData.get('key');
          if (key) {
            onSuccess?.(action + key, xhr);
          } else {
            onSuccess?.(body, xhr);
          }
        }
      };
      Object.keys(headers).forEach((h) => {
        if (headers[h] !== null) {
          xhr.setRequestHeader(h, headers[h]);
        }
      });
      console.log(method, action, typeof action);
      xhr.open(method, action);
      xhr.send(formData);
    };
    return publish();
  };
